package com.jnc.core.config.shiro.realm;

import com.jnc.common.constant.SysConstant;
import com.jnc.core.base.model.User;
import com.jnc.core.base.service.MenuService;
import com.jnc.core.base.service.RoleService;
import com.jnc.core.base.service.UserService;
import com.jnc.core.config.shiro.util.ShiroUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: jjn
 * @Date: 2018/9/20
 * @Desc:
 */
@Slf4j
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private RoleService roleService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private UserService userService;

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User user = ShiroUtil.getUser();
        List<String> roles = roleService.getRoleCodeByUser(user.getUserId());
        List<String> menus = menuService.queryPermsByUser(user.getUserId());
        List<String> menuList = null;
        //去除为null和空字符的权限
        if(menus != null && menus.size() > 0){
            menuList = menus.stream().filter(obj -> obj != null && !"".equals(obj)).collect(Collectors.toList());
        }
        //为当前用户设置角色和权限
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //管理员拥有所有权限
        if(user.isAdmin()){
            info.addRole("admin");
            info.addStringPermission("*:*:*");
        }else{
            info.addRoles(roles);
            info.addStringPermissions(menuList);
        }
        return info;
    }

    /**
     * 登录认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String userName = upToken.getUsername();

        User user = userService.getUserByLoginName(userName);
        if(null == user){
            throw new UnknownAccountException("用户不存在");
        }
        if(user.getStatus().intValue() == SysConstant.STATUS_CODE_ERROR){
            throw new LockedAccountException("账号已被锁定，请联系管理员");
        }

        //盐值：取用户信息中唯一的字段来生成盐值(password + loginName)，
        // 避免由于两个用户原始密码相同，加密后的密码也相同
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getLoginName()), getName());
        return info;
    }

    /**
     * 清除缓存权限
     */
    public void clearCachedAuthorizationInfo(){
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }
}
